<?php
// +----------------------------------------------------------------------
// | Library for ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2021 青海云音信息技术有限公司 [ http://www.yyinfos.com ]
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | gitee 代码仓库：https://gitee.com/qhweb/ThinkAdmin
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace qhweb\service;

use think\App;
use think\Container;
use Phinx\Config\Config;
use Phinx\Db\Adapter\AdapterFactory;
use think\migration\Migrator;
use think\admin\extend\PhinxExtend;
/**
 * 数据库管理器
 * Class ThinkService
 * @package qhweb\helper
 */

class ThinkService
{
    /**
     * 应用容器
     * @var App
     */
    public $app;

    /**
     * 数据库驱动
     * @var Db
     */
    public $adapter;

     /**
     * Constructor.
     * @param App $app
     */
    public function __construct(App $app)
    {
        $this->app = $app;
    }

    /**
     * 静态魔术方法
     * @param string $method 方法名称
     * @param array $args 调用参数
     * @return mixed|false|integer|QueryHelper
     */
    public static function __callStatic($method, $args)
    {
        return Container::getInstance()->invokeClass(static::class,[])->$method(...$args);
    }

    /**
     * 创建数据库实例
     * @template t of static
     * @param mixed $data
     */
    public static function Migrator($name='default',$version=0):object
    {
        $adapter = Container::getInstance()->invokeClass(static::class,[])->getAdapter();
        $migration = new Migrator($name,$version);
        $migration->setAdapter($adapter);
        return $migration;
    }

    /**
     * 验证数据表，不存在自动创建
     *
     * @param array $tables  数据表字段信息
     * @param string $type  操作类型install|uninstall
     * @return void
     */
    public static function checkTable($tables=[],$type="install")
    {
        if(empty($table)) return true;
        $migration = static::Migrator();
        foreach ($tables as $table => $conf) {
            if ($type == 'install' && !$migration->hasTable($table)) {
                $tabObj = $migration->table($table,[
                    'engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => $conf['comment'],
                ]);
                foreach ($conf['columns'] as $colName => $opt) {
                    $colType = $opt['type'];unset($opt['type']);
                    $tabObj->addColumn($colName,$colType,$opt);
                }
                $tabObj->addTimestamps();
                foreach (explode(',',$conf['indexs']) as $aliasName) {
                    $tabObj->addIndex($aliasName, ['name' => "idx_{$table}_{$aliasName}"]);
                }
                $tabObj->create();
                // 修改主键长度
                $migration->table($table)->changeColumn('id', 'integer', ['limit' => 11, 'identity' => true]);
            }

            if($type == 'uninstall' && $migration->hasTable($table)){
                $migration->dropTable($table);
            }
        }
        return true;
    }

    /**
     * 设置菜单
     *
     * @param [type] $data  菜单数据
     * @param string $parentName  父级菜单
     * @return void
     */
    public static function addMenu($data=[])
    {
        $menus = [];
        array_push($menus,$data);
        return PhinxExtend::write2menu($menus, ['url|node' => $data['url']]);
    }

    /**
     * 获取数据库驱动
     * @return array
     */
    protected function getAdapter()
    {
        if (isset($this->adapter)) {
            return $this->adapter;
        }

        $options = $this->getDbConfig();

        $adapter = AdapterFactory::instance()->getAdapter($options['adapter'], $options);

        if ($adapter->hasOption('table_prefix') || $adapter->hasOption('table_suffix')) {
            $adapter = AdapterFactory::instance()->getWrapper('prefix', $adapter);
        }

        $this->adapter = $adapter;

        return $adapter;
    }

    /**
     * 获取数据库配置
     * @return array
     */
    protected function getDbConfig(): array
    {
        $default = $this->app->config->get('database.default');

        $config = $this->app->config->get("database.connections.{$default}");

        if (0 == $config['deploy']) {
            $dbConfig = [
                'adapter'      => $config['type'],
                'host'         => $config['hostname'],
                'name'         => $config['database'],
                'user'         => $config['username'],
                'pass'         => $config['password'],
                'port'         => $config['hostport'],
                'charset'      => $config['charset'],
                'suffix'       => $config['suffix'] ?? '',
                'table_prefix' => $config['prefix'],
            ];
        } else {
            $dbConfig = [
                'adapter'      => explode(',', $config['type'])[0],
                'host'         => explode(',', $config['hostname'])[0],
                'name'         => explode(',', $config['database'])[0],
                'user'         => explode(',', $config['username'])[0],
                'pass'         => explode(',', $config['password'])[0],
                'port'         => explode(',', $config['hostport'])[0],
                'charset'      => explode(',', $config['charset'])[0],
                'suffix'       => explode(',', $config['suffix'] ?? '')[0],
                'table_prefix' => explode(',', $config['prefix'])[0],
            ];
        }

        $table = $this->app->config->get('database.migration_table', 'migrations');

        $dbConfig['migration_table'] = $dbConfig['table_prefix'] . $table;
        $dbConfig['version_order']   = Config::VERSION_ORDER_CREATION_TIME;

        return $dbConfig;
    }
}